package com.tianji.medical.service.Impl;


import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.common.Result;
import com.tianji.common.constant.CouponCacheConstant;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.SecurityUtil;
import com.tianji.coupon.pojo.Coupon;
import com.tianji.exception.BizException;
import com.tianji.medical.filter.BloomFilterConfig;
import com.tianji.medical.mapper.DoctorScheduleMapper;
import com.tianji.medical.pojo.DoctorSchedule;
import com.tianji.medical.pojo.dto.AppointmentRegistrationDto;
import com.tianji.medical.service.DoctorScheduleService;
import com.tianji.mq.produce.DoctorScheduleProduce;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

import static com.tianji.common.constant.CouponCacheConstant.APPOINTMENT_CACHE_KEY_PREFIX;
import static com.tianji.common.utils.DateUtils.convertTimestampToLocalDateTime;

/**
 * <p>
 * 医生号源表 服务实现类
 * </p>
 *
 * @author 陈佳
 * @since 2024-10-14
 */
@Service
@RequiredArgsConstructor
public class DoctorScheduleServiceImpl extends ServiceImpl<DoctorScheduleMapper, DoctorSchedule> implements DoctorScheduleService {

    private final BloomFilterConfig bloomFilter;

    private final RedisTemplate redisTemplate;

    private final DoctorScheduleProduce doctorScheduleProduce;

    @Override
    public Result appointmentRegistration(AppointmentRegistrationDto dto) {
        String key = dto.getPatientId()+":"+dto.getDoctorId()+":"+dto.getAppointTime();
        Long userId = SecurityUtil.getUser().getUserId();
        //使用布隆过滤器校验是否已经是预约过了
        if(bloomFilter.mightContain(key)){
            throw new BizException("已经预约过了此医生!");
        }
        //校验号源库存信息
        DoctorSchedule doctorSchedule = queryAppointmentByCache(dto.getId());
        if(doctorSchedule == null){
            throw new BizException("此号源信息不存在");
        }

        if(doctorSchedule.getAvailableSlots() == 0){
            throw new BizException("今日号源已满，请另选日期");
        }

        //号源扣减
        redisTemplate.opsForHash().increment(APPOINTMENT_CACHE_KEY_PREFIX+dto.getId(),"availableSlots",-1);
        //使用mq进行异步新增
        HashMap<String, Object> map = new HashMap<>();
        map.put("id", dto.getId());
        map.put("userId", userId);
        try {
            doctorScheduleProduce.sendCouponUpdateMessage(map);
        } catch (Exception e) {
            //需要恢复到原来的库存
            redisTemplate.opsForHash().increment(
                    CouponCacheConstant.APPOINTMENT_CACHE_KEY_PREFIX+dto.getId(),"totalNum",1
            );
            throw new RuntimeException(e);
        }
        return null;
    }


    private DoctorSchedule queryAppointmentByCache(Long appointId) {
        String key = APPOINTMENT_CACHE_KEY_PREFIX+appointId;
        Map map = redisTemplate.opsForHash().entries(key);
        if(map.isEmpty()){
            return null;
        }
        DoctorSchedule schedule = new DoctorSchedule();
        schedule.setId(Long.parseLong(map.get("id").toString()));
        schedule.setAvailableSlots(Integer.parseInt(map.get("availableSlots").toString()));
        schedule.setDate(convertTimestampToLocalDateTime(map.get("date")));
        schedule.setTotalSlots(Integer.parseInt(map.get("totalSlots").toString()));
        schedule.setDoctorId(Long.parseLong(map.get("doctorId").toString()));
        return schedule;
    }

}
